home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Magazine / C_Tutorial / Part-5 / multiwin1.c < prev    next >
C/C++ Source or Header  |  1997-09-30  |  14KB  |  571 lines

  1. #include<exec/libraries.h>
  2. #include<intuition/intuition.h>
  3. #include<utility/tagitem.h>
  4. #include<graphics/text.h>
  5. #include<graphics/rastport.h>
  6. #include<intuition/screens.h>
  7. #include<libraries/gadtools.h>
  8.  
  9. #include<string.h>
  10. #include<stdio.h>
  11.  
  12. #include<clib/exec_protos.h>
  13. #include<clib/graphics_protos.h>
  14. #include<clib/intuition_protos.h>
  15. #include<clib/gadtools_protos.h>
  16.  
  17. /* The library base global variables */
  18. /* (The different style of opening libraries requires these to be initialised to NULL) */
  19. struct Library* GfxBase = NULL;
  20. struct Library* IntuitionBase = NULL;
  21. struct Library* GadToolsBase = NULL;
  22.  
  23. /* The global handle on the palette gadget */
  24. struct Gadget* palgad = NULL;
  25. /* Global record of foreground pen */
  26. UBYTE pen;
  27. /* Global records of our windows */
  28. struct Window* drawwin = NULL;
  29. struct Window* toolwin = NULL;
  30. /* Global record of title bar height */
  31. int offtop;
  32. /* Global record of our menu strip */
  33. struct Menu* menustrip = NULL;
  34. /* Global record of the screen's visual information */
  35. APTR vinfo = NULL;
  36. /* Global record of our gadget list */
  37. struct Gadget* glist = NULL;
  38. /* Global record of our screen */
  39. struct Screen* scr = NULL;
  40. /* Global flag for whether the tool window should be open */
  41. int opentw = TRUE;
  42.  
  43. /* Need to give prototypes for our functions */
  44. int  createAll();
  45. void freeAll();
  46. int  openLibs();
  47. void closeLibs();
  48. int  openScr();
  49. void closeScr();
  50. int  createMenuStrip();
  51. void freeMenuStrip();
  52. int  openToolWin();
  53. void closeToolWin();
  54. int  openDrawWin();
  55. void closeDrawWin();
  56. int  createGadgets();
  57. void freeGadgets();
  58. void handleIDCMP();
  59. int  checkToolWin();
  60. void setFgPen(int);
  61. void doGadgetUp(struct IntuiMessage*);
  62. int  doMenuPick(struct IntuiMessage*);
  63.  
  64. /* Some constants for the position and size of our gadget */
  65. #define MYBUT_LEFT        (10)
  66. #define MYBUT_TOP            (5)
  67. #define MYBUT_WIDTH        (80)
  68. #define MYBUT_HEIGHT    (12)
  69. #define MYBUT_TEXT        "Next Pen"
  70. #define MYBUT_ID            (0)
  71.  
  72. #define MYPAL_LEFT        (170)
  73. #define MYPAL_TOP            (1)
  74. #define MYPAL_WIDTH        (109)
  75. #define MYPAL_HEIGHT    (19)
  76. #define MYPAL_TEXT        "Colour:"
  77. #define MYPAL_ID            (1)
  78. #define MYPAL_DEPTH        (4)
  79.  
  80. /* The top gap required around the gadgets */
  81. #define MYTOPGAP      (21)
  82.  
  83. /* The initial pen colour */
  84. #define MYINITPEN            (1)
  85.  
  86. /* The start of the program */
  87. void main()
  88. {
  89.     /* Use a different style of opening libraries... */
  90.     if(createAll())
  91.     {
  92.         /* Now do the real work */
  93.         handleIDCMP();
  94.     }
  95.     /* Matched call to close libraries */
  96.     freeAll();
  97. }
  98.  
  99. int createAll()
  100. {
  101.     return openLibs() && openScr() && createMenuStrip() && createGadgets() && openToolWin() && openDrawWin();
  102. }
  103.  
  104. void freeAll()
  105. {
  106.     closeDrawWin();
  107.     closeToolWin();
  108.     freeGadgets();
  109.     freeMenuStrip();
  110.     closeScr();
  111.     closeLibs();
  112. }
  113.  
  114. /* Try to open all the libraries -- return TRUE on success */
  115. int openLibs()
  116. {
  117.     if((GfxBase = OpenLibrary("graphics.library",37)) == NULL)
  118.     {
  119.         printf("Error: could not open graphics.library\n");
  120.         return FALSE;
  121.     }
  122.     if((IntuitionBase = OpenLibrary("intuition.library",37)) == NULL)
  123.     {
  124.         printf("Error: could not open intuition.library\n");
  125.         return FALSE;
  126.     }
  127.     if((GadToolsBase = OpenLibrary("gadtools.library",37)) == NULL)
  128.     {
  129.         printf("Error: could not open gadtools.library\n");
  130.         return FALSE;
  131.     }
  132.   return TRUE;
  133. }
  134.  
  135. /* Close any open library */
  136. void closeLibs()
  137. {
  138.     if(GadToolsBase)
  139.         CloseLibrary(GadToolsBase);
  140.     if(IntuitionBase)
  141.         CloseLibrary(IntuitionBase);
  142.     if(GfxBase)
  143.         CloseLibrary(GfxBase);
  144. }
  145.  
  146. /* Open screen and setup GadTools stuff */
  147. int openScr()
  148. {
  149.     UWORD pens[] = { ~0 };
  150.     /* Try to open a new screen with 16 colours (four bitplanes deep) */
  151.     if(scr = OpenScreenTags(NULL,
  152.                                                     SA_Depth,    4,
  153.                                                     /* Enable 3D look by specifying SA_Pens */
  154.                                                     SA_Pens,    pens,
  155.                                                     SA_Title,    "Hello World Painter",
  156.                                                     TAG_DONE))
  157.     {
  158.         /* Get the visual info so GadTools can render the gadgets nicely */
  159.         if(vinfo = GetVisualInfo(scr, TAG_DONE))
  160.             /* Succeeded */
  161.             return TRUE;
  162.         else
  163.             printf("Error: could not get visual info\n");
  164.     }
  165.     else
  166.         printf("Error: could not create screen\n");
  167.     /* Failed */
  168.     return FALSE;
  169. }
  170.  
  171. void closeScr()
  172. {
  173.     if(vinfo)
  174.     {
  175.         FreeVisualInfo(vinfo);
  176.         vinfo = NULL;
  177.     }
  178.     if(scr)
  179.     {
  180.         CloseScreen(scr);
  181.         scr = NULL;
  182.     }
  183. }
  184.  
  185. /* Create the menu strip, using GadTools menu functions */
  186. int createMenuStrip()
  187. {
  188.     /* The description of our menus */
  189.     struct NewMenu mymenu[] =
  190.     {
  191.         { NM_TITLE, "Project",            0,        0, 0, 0,},
  192.         {  NM_ITEM,        "Quit",                "Q",    0, 0, 0,},
  193.         { NM_TITLE, "Pen",                    0,        0, 0, 0,},
  194.         {  NM_ITEM,        "Next",                "N",    0, 0, 0,},
  195.         {  NM_ITEM,        "Prev",                "P",    0, 0, 0,},
  196.         {  NM_ITEM,        NM_BARLABEL,    0,        0, 0, 0,},
  197.         {  NM_ITEM,        "Reset",            "R",    0, 0, 0,},
  198.         { NM_TITLE, "Tools",                0,        0, 0, 0,},
  199.         {  NM_ITEM,        "Screen Bar",    "S",    CHECKIT | MENUTOGGLE | CHECKED, 0, 0,},
  200.         {  NM_ITEM,        "Tool Bar",        "T",    CHECKIT | MENUTOGGLE | CHECKED, 0, 0,},
  201.         {   NM_END, NULL,                        0,        0, 0, 0,},
  202.     };
  203.     if (menustrip = CreateMenus(mymenu, TAG_END))
  204.     {
  205.         if (LayoutMenus(menustrip, vinfo, TAG_END))
  206.             /* Succeeded */
  207.             return TRUE;
  208.         else
  209.             printf("Error: could not layout menus\n");
  210.     }
  211.     else
  212.         printf("Error: could not create menu strip\n");
  213.     /* Failed */
  214.     return FALSE;
  215. }
  216.  
  217. void freeMenuStrip()
  218. {
  219.     if(menustrip)
  220.     {
  221.         FreeMenus(menustrip);
  222.         menustrip = NULL;
  223.     }
  224. }
  225.  
  226. /* Actually open the windows, in the normal way */
  227. int openToolWin()
  228. {
  229.     /* Extra protection -- only open if not already open */
  230.     if(toolwin == NULL)
  231.     {
  232.         /* The minimal height of our tool window */
  233.         int h = MYTOPGAP + offtop + scr->WBorBottom;
  234.         /* Open our tool window */
  235.         if(toolwin = OpenWindowTags(NULL,
  236.                                                                 WA_Left,                    0,
  237.                                                                 WA_Top,                        scr->Height - h,
  238.                                                                 /* Make the window sit in the bottom of the screen */
  239.                                                                 WA_Width,                    scr->Width,
  240.                                                                 WA_Height,                h,
  241.                                                                 WA_Flags,                    WFLG_CLOSEGADGET | WFLG_DRAGBAR,
  242.                                                                 WA_IDCMP,                    IDCMP_CLOSEWINDOW | BUTTONIDCMP | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK,
  243.                                                                 WA_Gadgets,                glist,
  244.                                                                 WA_CustomScreen,    scr,
  245.                                                                 WA_Title,                    "Tools",
  246.                                                                 TAG_DONE,                    0))
  247.         {
  248.             /* Attach menu strip to tool window, as well */
  249.             if(SetMenuStrip(toolwin, menustrip))
  250.             {
  251.                 /* Let GadTools refresh its bits of the tool window */
  252.                 GT_RefreshWindow(toolwin, NULL);
  253.                 return TRUE;
  254.             }
  255.             else
  256.                 printf("Error: could not attach menus to tool window\n");
  257.         }
  258.         else
  259.             printf("Error: could not open tool window\n");
  260.     }
  261.     else
  262.         printf("Warning: tool window already open\n");
  263.     return FALSE;
  264. }
  265.  
  266. void closeToolWin()
  267. {
  268.     if(toolwin)
  269.     {
  270.         ClearMenuStrip(toolwin);
  271.         CloseWindow(toolwin);
  272.         toolwin = NULL;
  273.     }
  274. }
  275.  
  276. int openDrawWin()
  277. {
  278.     /* Open our drawing window */
  279.     if(drawwin = OpenWindowTags(NULL,
  280.                                                             WA_Left,                    0,
  281.                                                             WA_Top,                        0,
  282.                                                             /* Make the window the same size as the screen */
  283.                                                             WA_Width,                    scr->Width,
  284.                                                             WA_Height,                scr->Height,
  285.                                                             WA_Flags,                    WFLG_BACKDROP | WFLG_BORDERLESS | WFLG_REPORTMOUSE,
  286.                                                             WA_IDCMP,                    IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK,
  287.                                                             WA_CustomScreen,    scr,
  288.                                                             TAG_DONE,                    0))
  289.     {
  290.         /* Set the drawing mode to draw only the foreground of text, not the background */
  291.         SetDrMd(drawwin->RPort, JAM1);
  292.         /* Attach menu strip to drawing window */
  293.         if(SetMenuStrip(drawwin, menustrip))
  294.             return TRUE;
  295.         else
  296.             printf("Error: could not attach menus to drawing window\n");
  297.     }
  298.     else
  299.         printf("Error: could not open drawing window\n");
  300.     return FALSE;
  301. }
  302.  
  303. void closeDrawWin()
  304. {
  305.     if(drawwin)
  306.     {
  307.         ClearMenuStrip(drawwin);
  308.         CloseWindow(drawwin);
  309.         drawwin = NULL;
  310.     }
  311. }
  312.  
  313. int createGadgets()
  314. {
  315.     struct Gadget* gad;
  316.     int offleft;
  317.     struct NewGadget newgad;
  318.     /* Initialised structure declaration: describes 8pt Topaz font */
  319.     struct TextAttr topazFont = { "topaz.font", 8, 0, 0, };
  320.     /* Start a GadTools gadget list */
  321.     gad = CreateContext(&glist);
  322.     /* The offsets of our window borders */
  323.     offleft = scr->WBorLeft;
  324.     offtop = scr->WBorTop + (scr->Font->ta_YSize + 1);
  325.  
  326.     /* Setup our first gadget */
  327.     newgad.ng_TextAttr         = &topazFont;
  328.     newgad.ng_VisualInfo     = vinfo;
  329.     newgad.ng_LeftEdge         = MYBUT_LEFT + offleft;
  330.     newgad.ng_TopEdge         = MYBUT_TOP + offtop;
  331.     newgad.ng_Width             = MYBUT_WIDTH;
  332.     newgad.ng_Height             = MYBUT_HEIGHT;
  333.     newgad.ng_GadgetText    = MYBUT_TEXT;
  334.     newgad.ng_GadgetID        = MYBUT_ID;
  335.     newgad.ng_Flags                = 0;
  336.     /* Now create it and add it to our list */
  337.     gad = CreateGadget(BUTTON_KIND, gad, &newgad, TAG_END);
  338.  
  339.     /* Setup our second gadget */
  340.     /* (We can reuse newgad, and just change the different bits) */
  341.     newgad.ng_LeftEdge         = MYPAL_LEFT + offleft;
  342.     newgad.ng_TopEdge         = MYPAL_TOP + offtop;
  343.     newgad.ng_Width             = MYPAL_WIDTH;
  344.     newgad.ng_Height             = MYPAL_HEIGHT;
  345.     newgad.ng_GadgetText    = MYPAL_TEXT;
  346.     newgad.ng_GadgetID        = MYPAL_ID;
  347.     newgad.ng_Flags                = 0;
  348.     /* Now create it and add it to our list */
  349.     gad = CreateGadget(    PALETTE_KIND, gad, &newgad,
  350.                                             /* Initially selected pen */
  351.                                             GTPA_Color, MYINITPEN,
  352.                                             /* Depth: 2 to the power MYPAL_DEPTH colours */
  353.                                             GTPA_Depth, MYPAL_DEPTH,
  354.                                             /* Gadget will indicate selection */
  355.                                             GTPA_IndicatorWidth, 16,
  356.                                             TAG_DONE);
  357.  
  358.     /* Remember gadget pointer so we can affect it in message handler */
  359.     palgad = gad;
  360.     /* Success if we managed final allocation */
  361.     return (gad != NULL);
  362. }
  363.  
  364. void freeGadgets()
  365. {
  366.     if(glist)
  367.     {
  368.         FreeGadgets(glist);
  369.         glist = NULL;
  370.         /* Reset palgad pointer, too */
  371.         palgad = NULL;
  372.     }
  373. }
  374.  
  375. /* Our message handling code */
  376. void handleIDCMP()
  377. {
  378.     char* text = "Hello World!";
  379.     int going = TRUE;
  380.     int drawing = FALSE;
  381.     ULONG drawsig, toolsig, gotsig;
  382.     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  383.     setFgPen(MYINITPEN);
  384.     while(going)
  385.     {
  386.         struct IntuiMessage* intuimsg;
  387.         /* Only include tool window signal mask if window is open */
  388.         toolsig = opentw ? 1 << toolwin->UserPort->mp_SigBit : 0;
  389.         /* Wait for messages to arrive */
  390.         gotsig = Wait(drawsig | toolsig);
  391.         /* Messages have arrived: loop through all of them */
  392.         /* Check messages from the drawing window first */
  393.         if(gotsig & drawsig)
  394.         {
  395.             while(intuimsg = GT_GetIMsg(drawwin->UserPort))
  396.             {
  397.                 /* Act on this message... */
  398.                 switch(intuimsg->Class)
  399.                 {
  400.                 case IDCMP_MOUSEBUTTONS:
  401.                     switch(intuimsg->Code)
  402.                     {
  403.                     case SELECTDOWN:
  404.                         drawing = TRUE;
  405.                         break;
  406.                     case SELECTUP:
  407.                         drawing = FALSE;
  408.                         break;
  409.                     }
  410.                     /* break; omitted so we draw on click, too */
  411.                 case IDCMP_MOUSEMOVE:
  412.                     if(drawing)
  413.                     {
  414.                         Move(drawwin->RPort, intuimsg->MouseX, intuimsg->MouseY);
  415.                         Text(drawwin->RPort, text, strlen(text));
  416.                     }
  417.                     break;
  418.                 case IDCMP_MENUPICK:
  419.                     going = doMenuPick(intuimsg);
  420.                     break;
  421.                 }
  422.                 /* Reply when finished with message */
  423.                 GT_ReplyIMsg(intuimsg);
  424.             }
  425.         }
  426.         /* Now check messages from the tool window */
  427.         if(going && (gotsig & toolsig))
  428.         {
  429.             while(intuimsg = GT_GetIMsg(toolwin->UserPort))
  430.             {
  431.                 /* Act on this message... */
  432.                 switch(intuimsg->Class)
  433.                 {
  434.                 case IDCMP_CLOSEWINDOW:
  435.                     {
  436.                         struct MenuItem* item;
  437.                         opentw = FALSE;
  438.                         /* Unset menu check mark */
  439.                         /* First, remove menu strip from windows */
  440.                         ClearMenuStrip(drawwin);
  441.                         ClearMenuStrip(toolwin);
  442.                         /* Menu 2, Item 1 is Tool Bar */
  443.                         item = ItemAddress(menustrip, FULLMENUNUM(2,1,0));
  444.                         /* Unset CHECKED flag */
  445.                         item->Flags &= ~CHECKED;
  446.                         /* Reattach menu strip to windows */
  447.                         ResetMenuStrip(toolwin,menustrip);
  448.                         ResetMenuStrip(drawwin,menustrip);
  449.                         break;
  450.                     }
  451.                 case IDCMP_REFRESHWINDOW:
  452.                     /* You *MUST* remember to ask for and handle these refresh messages */
  453.                     GT_BeginRefresh(toolwin);
  454.                     GT_EndRefresh(toolwin, TRUE);
  455.                     break;
  456.                 case IDCMP_GADGETUP:
  457.                     doGadgetUp(intuimsg);
  458.                     break;
  459.                 case IDCMP_MENUPICK:
  460.                     going = doMenuPick(intuimsg);
  461.                     break;
  462.                 }
  463.                 /* Reply when finished with message */
  464.                 GT_ReplyIMsg(intuimsg);
  465.             }
  466.         }
  467.         /* Check tool window if still going */
  468.         if(going)
  469.             going = checkToolWin();
  470.     }
  471. }
  472.  
  473. /* Check whether tool window should be opened or closed */
  474. int checkToolWin()
  475. {
  476.     if(toolwin)
  477.     {
  478.         if(!opentw)
  479.             closeToolWin();
  480.     }
  481.     else
  482.     {
  483.         if(opentw && !openToolWin())
  484.              return FALSE;  /* Error! Re-open failed */
  485.     }
  486.     return TRUE;
  487. }
  488.  
  489. /* Set foreground pen of drawing window */
  490. void setFgPen(int value)
  491. {
  492.     /* Wrap when reached the end of the palette gadget's colours */
  493.     pen = value % (1<<MYPAL_DEPTH);
  494.     /* Only set pen if window is open */
  495.     if(drawwin)
  496.         SetAPen(drawwin->RPort, pen);
  497.     /* If the palette gadget has been made, update it with new pen value */
  498.     if(palgad)
  499.         GT_SetGadgetAttrs(palgad, toolwin, NULL, GTPA_Color, pen, TAG_DONE);
  500. }
  501.  
  502. /* Process IDCMP_GADGETUP event */
  503. void doGadgetUp(struct IntuiMessage* intuimsg)
  504. {
  505.     struct Gadget* gad = (struct Gadget*)(intuimsg->IAddress);
  506.     switch(gad->GadgetID)
  507.     {
  508.     case MYBUT_ID:
  509.         /* Our button was clicked!  Set foreground to next pen colour */
  510.         setFgPen(pen+1);
  511.         break;
  512.     case MYPAL_ID:
  513.         /* Our palette gadget was clicked!  Set foreground to gadget colour */
  514.         setFgPen(intuimsg->Code);
  515.         break;
  516.     }
  517. }
  518.  
  519. /* Process IDCMP_MENUPICK event */
  520. int doMenuPick(struct IntuiMessage* intuimsg)
  521. {
  522.     UWORD menuCode, menuNumber, itemNumber;
  523.     /* Loop over all the menu selections in the menu code */
  524.     struct MenuItem* item;
  525.     for(menuCode = intuimsg->Code;
  526.             menuCode != MENUNULL;
  527.             menuCode = item->NextSelect)
  528.     {
  529.         item = ItemAddress(menustrip, menuCode);
  530.         /* Extract the menu number and menu item number from the menu code */
  531.         menuNumber = MENUNUM(menuCode);
  532.         itemNumber = ITEMNUM(menuCode);
  533.         /* Now decide what to do based on what menu item was selected */
  534.         switch(menuNumber)
  535.         {
  536.         case 0:  /* Project menu */
  537.             /* Only one item: Quit */
  538.             if(itemNumber == 0)
  539.                 return FALSE;  /* Stop going */
  540.             break;
  541.         case 1:  /* Pen menu */
  542.             switch(itemNumber)
  543.             {
  544.             case 0:  /* Next */
  545.                 setFgPen(pen+1);
  546.                 break;
  547.             case 1:  /* Prev */
  548.                 setFgPen(pen-1);
  549.                 break;
  550.             case 3:  /* Reset (item 2 is the bar!) */
  551.                 setFgPen(MYINITPEN);
  552.                 break;
  553.             }
  554.             break;
  555.         case 2:  /* Tools menu */
  556.             switch(itemNumber)
  557.             {
  558.             case 0:  /* Screen Bar */
  559.                 ShowTitle(scr, item->Flags & CHECKED);
  560.                 break;
  561.             case 1:  /* Tool Bar */
  562.                 /* Set state to indicate whether the tool window should be open */
  563.                 opentw = (item->Flags & CHECKED);
  564.                 break;
  565.             }
  566.         }
  567.     }
  568.     /* Keep going */
  569.     return TRUE;
  570. }
  571.